﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Direct.Core;
using System.Collections.ObjectModel;
using Direct.Security;

namespace Direct.Shell
{
    class ShellDesktopService : IShellDesktopService
    {
        private List<IShellMenuItem> _menuItems = new List<IShellMenuItem>();
        private List<IShellMenuItem> _toolLinks = new List<IShellMenuItem>();

        public ShellDesktopService()
        {
            MenuItems = new ReadOnlyCollection<IShellMenuItem>(_menuItems);
            ToolLinks = new ReadOnlyCollection<IShellMenuItem>(_toolLinks);
        }

        private IList<IShellMenuItem> GetItemsList(ShellMenuItemType itemType)
        {
            switch (itemType)
            {
                case ShellMenuItemType.MenuItem:
                    return _menuItems;

                case ShellMenuItemType.ToolLink:
                    return _toolLinks;

                default:
                    throw new InvalidOperationException("Não existe uma lista para os items do tipo {0}".Templ(itemType));
            }
        }

        public IShellMenuItem AddItem(string id, string group, string caption, ShellLinkBehavior behavior, int order, string hint, string url, string authKeyPath)
        {
            return CreateItemInternal(ShellMenuItemType.MenuItem, id, group, caption, behavior, order, hint, url, authKeyPath);
        }

        private IShellMenuItem CreateItemInternal(ShellMenuItemType shellMenuItemType, string id, string group, string caption, ShellLinkBehavior behavior, int order, string hint, string url, string authKeyPath)
        {
            Assert.EmptyString(id, "id");
            Assert.EmptyString(caption, "caption");
            Assert.EmptyString(url, "url");
            Assert.EmptyString(authKeyPath, "authKeyPath");

            var collection = GetItemsList(shellMenuItemType);

            if (collection.Any(item => item.Id.EqualsIgnoreCase(id)))
                throw new InvalidOperationException("Já existe um item de menu ou link com este id: {0}".Templ(id));

            var menuItem = new ShellMenuItem()
            {
                Id = id,
                AuthorizationKey = authKeyPath,
                Behavior = behavior,
                Caption = caption,
                Group = group,
                Hint = hint,
                ItemType = shellMenuItemType,
                Order = order,
                Url = url
            };
            collection.Add(menuItem);
            return menuItem;
        }

        public void Remove(IShellMenuItem item)
        {
            _menuItems.Remove(item);
            _toolLinks.Remove(item);
        }

        public IShellMenuItem AddToolLink(string id, string caption, ShellLinkBehavior behavior, int order, string hint, string url, string authKey)
        {
            return CreateItemInternal(ShellMenuItemType.ToolLink, id, "", caption, behavior, order, hint, url, authKey);
        }

        public ReadOnlyCollection<IShellMenuItem> MenuItems { get; private set; }
        public ReadOnlyCollection<IShellMenuItem> ToolLinks { get; private set; }

        public IEnumerable<IShellMenuItem> GetItemsForUser(ShellMenuItemType itemType, IUser user)
        {
            var collection = GetItemsList(itemType);
            var authorizationService = ServiceLocator.GetInstance<IAuthorizationService>();
            return collection.Where(item => item.AuthorizationKey.IsEmpty()
                || authorizationService.IsUserAuthorized(user.Login, item.AuthorizationKey));
        }

        private class ShellMenuItem : IShellMenuItem
        {
            public string Id { get; internal set; }
            public ShellMenuItemType ItemType { get; internal set; }
            public ShellLinkBehavior Behavior { get; set; }
            public string Caption { get; set; }
            public string Hint { get; set; }
            public string AuthorizationKey { get; set; }
            public string Url { get; set; }
            public string Group { get; set; }
            public int Order { get; set; }
        }
    }
}
